

#ifndef LTHASH_H
#define LTHASH_H

#include "ltdb.h"
#include "ltlst.h"
#include "os/ltmutex.h"


#define LT_HASH_NODE \
    lt_hash_node_t  hash_node

typedef struct lt_hash_node_struct lt_hash_node_t;
struct lt_hash_node_struct
{
    LT_LST_LINK(lt_hash_node_t);

    void*   value;
};

typedef struct lt_hash_cell_struct lt_hash_cell_t;
struct lt_hash_cell_struct
{
    LT_LST_BASE(lt_hash_node_t) node_lst;
};

typedef struct lt_hash_table_struct lt_hash_table_t;
struct lt_hash_table_struct
{
    lt_mutex_t          mutex;
    mem_obj_t*          mo;

    schar*              name;
    uint32              n_cells;
    lt_hash_cell_t*     cell_arr;
};

#define LT_HASH_INSERT(type, table, key, value) \
{\
    lt_hash_cell_t* cell;\
\
    cell = &(hash_table->cell_arr[key]);\
    ((type*)value)->hash_node.value = value;\
    LT_LST_ADD_LAST(cell->node_lst, &((type*)node)->hash_node);\
}

#define LT_HASH_DELETE(table, key, value) \
{\
    lt_hash_cell_t* cell;\
    lt_hash_node_t* node;\
\
    cell = &(hash_table->cell_arr[key]);\
    node = LT_LST_GET_FIRST(cell->node_lst);\
    while (node != NULL)\
    {\
        if (node->value == ((void*)value))\
        {\
            LT_LST_REMOVE(cell->node_lst, node);\
        }\
        node = LT_LST_GET_NEXT(node);\
    }\
}

#define LT_HASH_FIND(type, table, key, value, test) \
{\
    lt_hash_cell_t* cell;\
    lt_hash_node_t* node;\
\
    cell = &(hash_table->cell_arr[key]);\
    node = LT_LST_GET_FIRST(cell->node_lst);\
    while (node != NULL)\
    {\
        if (test)\
        {\
            value = (type*)(node->value);\
        }\
        else\
        {\
            node = LT_LST_GET_NEXT(node);\
        }\
    }\
}


lt_hash_table_t*
lt_hash_create(
    schar*      name,
    uint32      n
);

void
lt_hash_free(
    lt_hash_table_t*    hash_table             
);

#endif // #ifndef LTHASH_H